//
//  ReplayKitExample.swift
//  SwiftCode
//
//  Created by yuhus on 2023/9/19.
//  https://developer.apple.com/videos/play/wwdc2021/10101
//  https://developer.apple.com/videos/play/wwdc2020/10633

import UIKit
import SnapKit
import ReplayKit

/// 麦克风和摄像头可用
/// - [ios视频swift中的图像/文本叠加](https://www.itguest.com/post/bhheja1a2.html)
final class ReplayKitExample: UIViewController {
  private var count: Int = 0
  private var timer: Timer?
  
  var isActive = false
  
  /// 摄像机视图
  private var cameraView: UIView?
  
  /// Capture 采集数据
  var assetWriter: AVAssetWriter?
  var videoInput: AVAssetWriterInput?
  var audioInput: AVAssetWriterInput?
  
  /// Broadcast 控制器
  var broadcastController: RPBroadcastController!
  
  deinit {
    Timber.d(#function)
  }
  
  override func viewDidLoad() {
    super.viewDidLoad()
    title = "只支持真机"
    view.backgroundColor = .white
    
    initView()
    initData()
  }
  
  private func initView() {
    [cameraButton, micButton, label, recordButton, captureButton].forEach { view.addSubview($0) }
    cameraButton.snp.makeConstraints { make in
      make.top.equalTo(view.safeAreaLayoutGuide).offset(20)
      make.leading.equalToSuperview().offset(16)
    }
    micButton.snp.makeConstraints { make in
      make.centerX.equalToSuperview().offset(16)
      make.centerY.equalTo(cameraButton)
    }
    label.snp.makeConstraints { make in
      make.edges.equalToSuperview()
    }
    recordButton.snp.makeConstraints { make in
      make.height.equalTo(42)
      make.top.equalTo(cameraButton.snp.bottom).offset(20)
      make.leading.trailing.equalToSuperview().inset(16)
    }
    captureButton.snp.makeConstraints { make in
      make.height.equalTo(42)
      make.top.equalTo(recordButton.snp.bottom).offset(20)
      make.leading.trailing.equalToSuperview().inset(16)
    }
  }
  
  private func initData() {
    RPScreenRecorder.shared().delegate = self
    
    cameraButton.isSelected = RPScreenRecorder.shared().isCameraEnabled
    micButton.isSelected = RPScreenRecorder.shared().isMicrophoneEnabled
    
    initCapture()
  }
  
  func getFilePathURL() -> URL? {
    let fileManager = FileManager.default
    guard let replaysPath = fileManager
      .urls(for: .documentDirectory, in: .userDomainMask)
      .first?
      .appendingPathComponent("replays") else { return nil }
    
    if !fileManager.fileExists(atPath: replaysPath.path) {
      try? fileManager.createDirectory(atPath: replaysPath.path, withIntermediateDirectories: true, attributes: nil)
    }
    return replaysPath
      .appendingPathComponent(UUID().uuidString)
      .appendingPathExtension("mp4")
  }
  
  func startTiming() {
    label.text = String(count)
    timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] _ in
      guard let self else { return }
      self.count += 1
      self.label.text = String(self.count)
    }
  }
  
  func stopTiming() {
    timer?.invalidate()
  }
  
  @objc private func cameraButtonTapped() {
    cameraButton.isSelected.toggle()
    RPScreenRecorder.shared().isCameraEnabled = cameraButton.isSelected
  }
  
  @objc private func micButtonTapped() {
    micButton.isSelected.toggle()
    RPScreenRecorder.shared().isMicrophoneEnabled = micButton.isSelected
  }
  
  func setupCameraView() {
    DispatchQueue.main.async {
      // Validate that the camera preview view and camera are in an enabled state.
      if (RPScreenRecorder.shared().cameraPreviewView != nil) && RPScreenRecorder.shared().isCameraEnabled {
        // Set the camera view to the camera preview view of RPScreenRecorder.
        guard let cameraView = RPScreenRecorder.shared().cameraPreviewView else {
          print("Unable to retrieve the cameraPreviewView from RPScreenRecorder. Returning.")
          return
        }

        self.view.addSubview(cameraView)
        cameraView.snp.makeConstraints { make in
          make.size.equalTo(100)
          make.centerX.equalToSuperview()
          make.centerY.equalToSuperview().multipliedBy(1.5)
        }
        self.cameraView = cameraView
      }
    }
  }
  
  func tearDownCameraView() {
    DispatchQueue.main.async {
      // Remove the camera view from the main view when tearing down the camera.
      self.cameraView?.removeFromSuperview()
    }
  }
  
  private func configReplayButton(_ button: UIButton) {
    button.backgroundColor = .black
    button.layer.cornerRadius = 8
  }
  
  private lazy var cameraButton: UIButton = {
    let button = UIButton()
    button.setTitle("Camera", for: .normal)
    button.setTitleColor(.systemGray4, for: .normal)
    button.setTitleColor(.blue, for: .selected)
    button.setImage(.camera_fill?.withTintColor(.systemGray4), for: .normal)
    button.setImage(.camera_fill?.withTintColor(.blue), for: .selected)
    button.addTarget(self, action: #selector(cameraButtonTapped), for: .touchUpInside)
    return button
  }()
  
  private lazy var micButton: UIButton = {
    let button = UIButton()
    button.setTitle("Microphone", for: .normal)
    button.setTitleColor(.systemGray4, for: .normal)
    button.setTitleColor(.blue, for: .selected)
    button.setImage(.mic_fill?.withTintColor(.systemGray4), for: .normal)
    button.setImage(.mic_fill?.withTintColor(.blue), for: .selected)
    button.addTarget(self, action: #selector(micButtonTapped), for: .touchUpInside)
    return button
  }()
  
  lazy var recordButton: UIButton = {
    let button = UIButton()
    button.setTitle("Start Recording", for: .normal)
    button.addTarget(self, action: #selector(recordButtonTapped), for: .touchUpInside)
    configReplayButton(button)
    return button
  }()
  
  lazy var captureButton: UIButton = {
    let button = UIButton()
    button.setTitle("Start Capture", for: .normal)
    button.addTarget(self, action: #selector(captureButtonTapped), for: .touchUpInside)
    configReplayButton(button)
    return button
  }()
  
  lazy var broadcastButton: UIButton = {
    let button = UIButton()
    button.setTitle("Start Broadcast", for: .normal)
    button.addTarget(self, action: #selector(broadcastButtonTapped), for: .touchUpInside)
    configReplayButton(button)
    return button
  }()
  
  lazy var clipButton: UIButton = {
    let button = UIButton()
    button.setTitle("Start Broadcast", for: .normal)
    button.addTarget(self, action: #selector(captureButtonTapped), for: .touchUpInside)
    configReplayButton(button)
    return button
  }()
  
  lazy var getClipButton: UIButton = {
    let button = UIButton()
    button.setTitle("Get Clip", for: .normal)
    button.addTarget(self, action: #selector(captureButtonTapped), for: .touchUpInside)
    configReplayButton(button)
    return button
  }()
  
  private lazy var label: UILabel = {
    let label = UILabel()
    label.font = .systemFont(ofSize: 180, weight: .bold)
    label.textColor = .green.withAlphaComponent(0.2)
    label.textAlignment = .center
    return label
  }()
}

extension ReplayKitExample: RPScreenRecorderDelegate {
  func screenRecorderDidChangeAvailability(_ screenRecorder: RPScreenRecorder) {
    // 屏幕录像机的可用性发生变化。
    DispatchQueue.main.async {
      self.recordButton.isEnabled = screenRecorder.isAvailable
      self.captureButton.isEnabled = screenRecorder.isAvailable
      self.broadcastButton.isEnabled = screenRecorder.isAvailable
      self.clipButton.isEnabled = screenRecorder.isAvailable
    }
  }
}

fileprivate extension UIImage {
  static let mic_fill = UIImage(systemName: "mic.fill")?
    .withTintColor(.gray, renderingMode: .alwaysOriginal)
    .withConfiguration(UIImage.SymbolConfiguration(pointSize: 28))
  
  static let camera_fill = UIImage(systemName: "camera.fill")?
    .withTintColor(.gray, renderingMode: .alwaysOriginal)
    .withConfiguration(UIImage.SymbolConfiguration(pointSize: 28))
}
